#include "light_effect_handle.h"
static TaskHandle_t thread_light_effect;
static uint8_t data[2000];

static void print_data_hex(uint8_t *data, u16 len)
{   
    for (int i = 0; i < len; i++) 
    {
        printf(" %02x", data[i]);
    }
    
    printf(", len1: %d\n", len);
}

void get_cache_data(u8 *buf)
{
	memcpy(buf,data,get_color_length());
	//print_data_hex(buf,get_color_length());
}

/*******************************************************************
 * @brief    设置ws281x颜色32位
 * @Author   
 * @DateTime 2024-04-01
 * @param    
 * @return   
 *******************************************************************/
uint32_t set_color_dazzling(uint8_t uv,uint8_t red,uint8_t green,uint8_t blue)
{
	return uv << 24 | red << 16 | green << 8 | blue;
}

/*******************************************************************
 * @brief    设置灯带任意灯珠颜色
 * @Author   
 * @DateTime 2024-06-03
 * @param    
 * @return   
 *******************************************************************/
void set_ws281x_color_1bit_dazzling(uint16_t num,uint32_t color)
{
    data[num*3+0]=(color >> 16) & 0xff;    		//R
    data[num*3+1]=(color >> 8) & 0xff;      	//G
    data[num*3+2]=color & 0xff;      			//B

}





/*******************************************************************
 * @brief    ws281x淡入淡出效果
 * @Author   
 * @DateTime 2024-06-12
 * @param    wait:淡入淡出延时
 *			 buff:RGB颜色数据
 *			 len:传入颜色数据长度
 * @return   
 *******************************************************************/
void set_ws281x_fade(uint8_t num,uint8_t wait,uint8_t len,uint8_t *buff)		//430ms@45段@AT32F421
{
	uint8_t red,green,blue,n;

	for(uint8_t i=0;i<len/3;i++)
	{
		red = buff[i*3+0]; 
		green = buff[i*3+1]; 
		blue = buff[i*3+2];
		
		n=(red>green)?red:green;  
		n=(n>blue)?n:blue;
		
		if(n==0x00)		
			n = 100;
		
		red = green = blue = 0;
		
		for(uint8_t j=0;j<n/FADE_SPEED;j++)	
		{

			if(((1000/(get_light_wait()+1))!=wait)||(get_light_len()!=len)||(get_light_effect_enum()!=num))
			{
				memset(data,0,2000);
				return;
			}

			for(uint8_t t=0;t<get_light_length();t++)
				set_ws281x_color_1bit_dazzling(t,set_color_dazzling(0,red,green,blue));
			
			if(red<buff[i*3+0])
				red+=FADE_SPEED;
			if(green<buff[i*3+1])
				green+=FADE_SPEED;
			if(blue<buff[i*3+2])
				blue+=FADE_SPEED;
			vTaskDelay(wait);
		}
		red = buff[i*3+0]; 
		green = buff[i*3+1]; 
		blue = buff[i*3+2];


		for(uint8_t j=0;j<n/FADE_SPEED;j++)
		{
			if(((1000/(get_light_wait()+1))!=wait)||(get_light_len()!=len)||(get_light_effect_enum()!=num))
			{
				memset(data,0,2000);
				return;
			}
			for(uint8_t t=0;t<=get_light_length();t++)
				set_ws281x_color_1bit_dazzling(t,set_color_dazzling(0,red,green,blue));

			if(red>=FADE_SPEED)
				red-=FADE_SPEED;
			if(green>=FADE_SPEED)
				green-=FADE_SPEED;
			if(blue>=FADE_SPEED)
				blue-=FADE_SPEED;
			vTaskDelay(wait);
		}
	}
}


/*******************************************************************
 * @brief    ws281x淡出效果
 * @Author   
 * @DateTime 2024-06-12
 * @param    wait:淡出延时
 *			 buff:RGB颜色数据
 *			 len:传入颜色数据长度
 * @return   
 *******************************************************************/
void set_ws281x_fade_out(uint8_t num,uint8_t wait,uint8_t len,uint8_t *buff)
{
	uint8_t red,green,blue,n;
	for(uint8_t i=0;i<len/3;i++)
	{
		red = buff[i*3+0]; 
		green = buff[i*3+1]; 
		blue = buff[i*3+2];
		
		n=(red>green)?red:green;  
		n=(n>blue)?n:blue;
		
		if(n==0x00)		
			n = 100;	
		
		for(uint8_t j=0;j<n/FADE_SPEED;j++)	
		{
			if(((1000/(get_light_wait()+1))!=wait)||(get_light_len()!=len)||(get_light_effect_enum()!=num))
			{
				memset(data,0,2000);
				return;
			}
			for(uint8_t t=0;t<=get_light_length();t++)
				set_ws281x_color_1bit_dazzling(t,set_color_dazzling(0,red,green,blue));
			
			if(red>=FADE_SPEED)
				red-=FADE_SPEED;
			if(green>=FADE_SPEED)
				green-=FADE_SPEED;
			if(blue>=FADE_SPEED)
				blue-=FADE_SPEED;
			vTaskDelay(pdMS_TO_TICKS(wait));
		}
	}
}


/*******************************************************************
 * @brief    ws281x淡入效果
 * @Author   
 * @DateTime 2024-06-12
 * @param    wait:淡入延时
 *			 buff:RGB颜色数据
 *			 len:传入颜色数据长度
 * @return   
 *******************************************************************/
void set_ws281x_fade_in(uint8_t num,uint8_t wait,uint8_t len,uint8_t *buff)		//430ms@45段@AT32F421
{
	uint8_t red,green,blue,n;

	for(uint8_t i=0;i<len/3;i++)
	{
		red = buff[i*3+0]; 
		green = buff[i*3+1]; 
		blue = buff[i*3+2];
		
		n=(red>green)?red:green;  
		n=(n>blue)?n:blue;
		
		if(n==0x00)		
			n = 100;
		
		red = green = blue = 0;
		
		for(uint8_t j=0;j<n/FADE_SPEED;j++)	
		{
			if(((1000/(get_light_wait()+1))!=wait)||(get_light_len()!=len)||(get_light_effect_enum()!=num))
			{
				memset(data,0,2000);
				return;
			}
			for(uint8_t t=0;t<=get_light_length();t++)
				set_ws281x_color_1bit_dazzling(t,set_color_dazzling(0,red,green,blue));
			
			if(red<buff[i*3+0])
				red+=FADE_SPEED;
			if(green<buff[i*3+1])
				green+=FADE_SPEED;
			if(blue<buff[i*3+2])
				blue+=FADE_SPEED;
			vTaskDelay(wait);
		}
	}
}

/*******************************************************************
 * @brief    数组数据后移
 * @Author   
 * @DateTime 2024-06-13
 * @param    buff:RGB颜色数据
 *			 len:传入颜色数据长度
 * @return   
 *******************************************************************/
void move_behind(uint32_t *buff,uint16_t len)
{
	uint32_t temp = buff[len-1];
	for (uint16_t i = len - 1; i >= 1; i--)
	{
		buff[i] = buff[i - 1];
	}
	buff[0] = temp;
}

/*******************************************************************
 * @brief    ws281x跑马逆时针
 * @Author   
 * @DateTime 2024-06-14
 * @param    wait:流水灯延时
 *			 buff:RGB颜色数据
 *			 len:传入颜色数据长度
 * @return   
 *******************************************************************/
void set_ws281x_marquee_counter_clockwise(uint8_t num,uint8_t wait,uint8_t len,uint8_t *buff)
{
	static uint32_t tape_lights_counter_clockwise_buff[BUF_SIZE] = {0x00};
	uint8_t t = 0;

	for(uint16_t n=0;n<get_light_length();n++)
	{
		tape_lights_counter_clockwise_buff[0] = buff[t] << 16 | buff[t+1] << 8 | buff[t+2];
		t+=3;
		if(t>=len-1)
			t = 0;
		
		for(uint8_t i=1;i<=get_light_length();i++)
			set_ws281x_color_1bit_dazzling(i,tape_lights_counter_clockwise_buff[i-1]);
		for(uint8_t i=0;i<10;i++)
		{
			if(((1000/(get_light_wait()+1))!=wait)||(get_light_len()!=len)||(get_light_effect_enum()!=num))
			{
				memset(data,0,2000);
				return;
			}
			vTaskDelay(wait);	
		}
		move_behind(tape_lights_counter_clockwise_buff,get_light_length());
	}
}

/*******************************************************************
 * @brief    数组数据前移
 * @Author   
 * @DateTime 2024-06-13
 * @param    buff:RGB颜色数据
 *			 len:传入颜色数据长度
 * @return   
 *******************************************************************/
void move_front(uint32_t *buff,uint16_t len)
{
	uint32_t temp = buff[0];
	for (uint16_t i = 0; i < len; i++)
	{
		buff[i] = buff[i + 1];
	}
	buff[len-1]=temp;
}

/*******************************************************************
 * @brief    ws281x跑马灯顺时针
 * @Author   
 * @DateTime 2024-06-13
 * @param    wait:流水灯延时
 *			 buff:RGB颜色数据
 *			 len:传入颜色数据长度
 * @return   
 *******************************************************************/
void set_ws281x_marquee_clockwise(uint8_t num,uint8_t wait,uint8_t len,uint8_t *buff)
{ 
	static uint32_t tape_lights_clockwise_buff[BUF_SIZE] = {0x00};
	uint8_t t = 0;

	for(uint16_t n=0;n<get_light_length();n++)
	{
		tape_lights_clockwise_buff[get_light_length()-1] = buff[t] << 16 | buff[t+1] << 8 | buff[t+2];
		t+=3;
		if(t>=len-1)
			t = 0;
		
		for(uint8_t i=1;i<=get_light_length();i++)
			set_ws281x_color_1bit_dazzling(i,tape_lights_clockwise_buff[i-1]);
		for(uint8_t i=0;i<10;i++)
		{
			if(((1000/(get_light_wait()+1))!=wait)||(get_light_len()!=len)||(get_light_effect_enum()!=num))
			{
				memset(data,0,2000);
				return;
			}
			vTaskDelay(wait);	
		}
		move_front(tape_lights_clockwise_buff,get_light_length());
	}
}

/*******************************************************************
 * @brief    ws281x全段闪烁
 * @Author   
 * @DateTime 2024-06-13
 * @param    wait:全段闪烁延时
 *			 buff:RGB颜色数据
 *			 len:传入颜色数据长度
 * @return   
 *******************************************************************/
void set_ws281x_flicker_all(uint8_t num,uint8_t wait,uint8_t len,uint8_t *buff)
{
	for(uint8_t i=0;i<len/3;i++)
	{
		for(uint8_t t=0;t<=get_light_length();t++)
			set_ws281x_color_1bit_dazzling(t,set_color_dazzling(0,buff[i*3+0],buff[i*3+1],buff[i*3+2]));
		for(uint8_t j=0;j<10;j++)
		{
			if(((1000/(get_light_wait()+1))!=wait)||(get_light_len()!=len)||(get_light_effect_enum()!=num))
			{
				memset(data,0,2000);
				return;
			}
			vTaskDelay(wait);
		}
		for(uint8_t t=0;t<=get_light_length();t++)
			set_ws281x_color_1bit_dazzling(t,set_color_dazzling(0,0,0,0));
		for(uint8_t j=0;j<10;j++)
		{
			if(((1000/(get_light_wait()+1))!=wait)||(get_light_len()!=len)||(get_light_effect_enum()!=num))
			{
				memset(data,0,2000);
				return;
			}
			vTaskDelay(wait);
		}
	}	
}

/*******************************************************************
 * @brief    ws281x分段闪烁
 * @Author   
 * @DateTime 2024-06-13
 * @param    wait:分段闪烁延时
 *			 buff:RGB颜色数据
 *			 len:传入颜色数据长度
 * @return   
 *******************************************************************/
void set_ws281x_flicker_subsection(uint8_t num,uint8_t wait,uint8_t len,uint8_t *buff)
{
	uint32_t tape_lights_buff[BUF_SIZE];
	uint8_t t = 0;

	for(uint8_t i=0;i<get_light_length();i++)
	{
		tape_lights_buff[i] = buff[t] << 16 | buff[t+1] << 8 | buff[t+2];
		t+=3;
		if(t>=len-1)
			t = 0;
	}	
	for(uint8_t i=0;i<len/3;i++)
	{
		for(uint8_t t=0;t<=get_light_length();t++)
			set_ws281x_color_1bit_dazzling(t,tape_lights_buff[t-1]);
		for(uint8_t j=0;j<10;j++)
		{
			if(((1000/(get_light_wait()+1))!=wait)||(get_light_len()!=len)||(get_light_effect_enum()!=num))
			{
				memset(data,0,2000);
				return;
			}
			vTaskDelay(wait);
		}
		for(uint8_t t=0;t<=get_light_length();t++)
			set_ws281x_color_1bit_dazzling(t,set_color_dazzling(0,0,0,0));
		for(uint8_t j=0;j<10;j++)
		{
			if(((1000/(get_light_wait()+1))!=wait)||(get_light_len()!=len)||(get_light_effect_enum()!=num))
			{
				memset(data,0,2000);
				return;
			}
			vTaskDelay(wait);
		}
	}	
}


/*******************************************************************
 * @brief    ws281x流星向后	
 * @Author   
 * @DateTime 2024-06-04
 * @param    
 * @return   
 *******************************************************************/
void ws281x_meteor_backwards(uint8_t len,uint32_t color, uint8_t wait) 
{
	const uint8_t num = 5;
	uint8_t red = (color >> 16) & 0xff;
	uint8_t green = (color >> 8) & 0xff;
	uint8_t blue = color & 0xff;

	uint8_t max_color = red;
	if(green > max_color)
		max_color = green;
	if(blue > max_color)
		max_color = blue;
	uint8_t instance = (max_color-200)/num;

	for(int i=len - 1; i>=-num; i--) 
	{
		for(uint8_t j = 0; j < num; j ++)
		{
			if(i + j >= 0 && i + j <= len)
			{
				int red_after = red - instance * j;
				int green_after = green - instance *  j;
				int blue_after = blue - instance *  j;
				if(j>=1)
				{
					red_after -= 200;
					green_after -= 200;
					blue_after -= 200;
				}
				set_ws281x_color_1bit_dazzling(i + j, set_color_dazzling(0,red_after >= 0 ? red_after : 0, green_after >= 0 ? green_after : 0, blue_after >= 0 ? blue_after : 0));
			}
		}
		if(i + num >= 0 && i+num <=get_light_length())
			set_ws281x_color_1bit_dazzling(i+num, 0); 
		vTaskDelay(wait);
	}
}

/*******************************************************************
 * @brief    ws281x流水灯向后
 * @Author   
 * @DateTime 2024-06-17
 * @param    wait:流水灯延时
 *			 buff:RGB颜色数据
 *			 len:传入颜色数据长度 
 * @return   
 *******************************************************************/
void set_ws281x_waterfall_light_counter_clockwise(uint8_t num,uint8_t wait,uint8_t len,uint8_t *buff)
{
	for(uint8_t i=0;i<len/3;i++)
	{
		if(((1000/(get_light_wait()+1))!=wait)||(get_light_len()!=len)||(get_light_effect_enum()!=num))
		{
			memset(data,0,2000);
			return;
		}
		ws281x_meteor_backwards(get_light_length(),set_color_dazzling(0,buff[i*3+0],buff[i*3+1],buff[i*3+2]),wait);
	}	
}

/*******************************************************************
 * @brief    ws281x流星向前
 * @Author   
 * @DateTime 2024-06-03
 * @param    
 * @return   
 *******************************************************************/
void ws281x_meteor_forward(uint8_t len,uint32_t color, uint8_t wait) 
{
	const uint8_t num = 5;

	uint8_t red = (color >> 16) & 0xff;
	uint8_t green = (color >> 8) & 0xff;
	uint8_t blue = color & 0xff;

	uint8_t max_color = red;
	if(green > max_color)
		max_color = green;
	if(blue > max_color)
		max_color = blue;
	uint8_t instance = (max_color-200)/num;
	for(uint16_t i=1; i<=len + num; i++) 
	{
		for(uint8_t j = 0; j < num; j ++)
		{
			if(i - j >= 0 && i - j <= len)
			{
				int red_after = red - (instance * j);
				int green_after = green - (instance * j);
				int blue_after = blue - (instance * j);

				if(j>=1)
				{
					red_after -= 200;
					green_after -= 200;
					blue_after -= 200;
				}
				set_ws281x_color_1bit_dazzling(i-j, set_color_dazzling(0,red_after >= 0?red_after:0,green_after >= 0?green_after:0,blue_after >= 0?blue_after:0));
			}
		}
		if(i - num >= 0 && i-num <= len)
			set_ws281x_color_1bit_dazzling(i-num,0); 
		vTaskDelay(wait);
	}
}

/*******************************************************************
 * @brief    ws281x流水灯向前
 * @Author   
 * @DateTime 2024-06-17
 * @param    wait:流水灯延时
 *			 buff:RGB颜色数据
 *			 len:传入颜色数据长度
 * @return   
 *******************************************************************/
void set_ws281x_waterfall_light_clockwise(uint8_t num,uint8_t wait,uint8_t len,uint8_t *buff)
{
	for(uint8_t i=0;i<len/3;i++)
	{
		if(((1000/(get_light_wait()+1))!=wait)||(get_light_len()!=len)||(get_light_effect_enum()!=num))
		{
			memset(data,0,2000);
			return;
		}
		ws281x_meteor_forward(get_light_length(),set_color_dazzling(0,buff[i*3+0],buff[i*3+1],buff[i*3+2]),wait);
	}
}

void zero_dazzling_delay(uint8_t num,uint8_t wait,uint8_t len,uint8_t *buff)
{
	memset(data,0,2000);
	vTaskDelay(20);
}

uint32_t ws281x_wheel1_dazzling(uint8_t wheelPos) 
{
	wheelPos = 255 - wheelPos;
	if(wheelPos < 85) 
	{
		return set_color_dazzling(0,255 - wheelPos * 3, 0, wheelPos * 3);
	}
	if(wheelPos < 170) 
	{
		wheelPos -= 85;
		return set_color_dazzling(0,0, wheelPos * 3, 255 - wheelPos * 3);
	}
	wheelPos -= 170;
	return set_color_dazzling(0,wheelPos * 3, 255 - wheelPos * 3, 0);
}

/*******************************************************************
 * @brief    ws281x彩虹灯反向
 * @Author   
 * @DateTime 2024-06-21
 * @param    
 * @return   
 *******************************************************************/

void ws281x_theater_chase_rainbow_reverse(uint8_t num,uint8_t wait,uint8_t len,uint8_t *buff)
{
	uint16_t i, j;
	for(j=0; j<256*10; j+=5) 
	{
		if(((1000/(get_light_wait()+1))!=wait)||(get_light_len()!=len)||(get_light_effect_enum()!=num))
		{
			memset(data,0,2000);
			return;
		}
		for(i=0;i<=get_light_length();i++) 
		{
			set_ws281x_color_1bit_dazzling(i,ws281x_wheel1_dazzling(((i*256/get_light_length())+j)&255));
		}
		vTaskDelay(wait);
	}
}

/*******************************************************************
 * @brief    ws281x彩虹灯正向
 * @Author   
 * @DateTime 2024-06-21
 * @param    
 * @return   
 *******************************************************************/
void ws281x_theater_chase_rainbow_forward(uint8_t num,uint8_t wait,uint8_t len,uint8_t *buff)
{
	uint16_t i, j;

	for(j=0; j<256*10; j+=5) 
	{
		if(((1000/(get_light_wait()+1))!=wait)||(get_light_len()!=len)||(get_light_effect_enum()!=num))
		{
			memset(data,0,2000);
			return;
		}
		
		for(i=0;i<=get_light_length();i++) 
		{
			set_ws281x_color_1bit_dazzling(get_light_length()-i,ws281x_wheel1_dazzling(((i*256/get_light_length())+j)&255));
		}
		vTaskDelay(wait);
	}
}

LIGHT_EFFECT light_effect_dazzling_handle[EFFECT_ENUM]=
{
    {zero_dazzling_delay},//效果0
    {set_ws281x_fade}, //淡入淡出效果
    {set_ws281x_fade_out}, //淡出效果
    {set_ws281x_fade_in}, //淡入效果
    {set_ws281x_marquee_counter_clockwise}, //跑马灯逆时针
    {set_ws281x_marquee_clockwise}, //跑马灯顺时针
    {set_ws281x_flicker_all}, //全段闪烁
    {set_ws281x_flicker_subsection}, //分段闪烁
    {set_ws281x_waterfall_light_counter_clockwise}, //流水向后
    {set_ws281x_waterfall_light_clockwise},//流水向前
    {ws281x_theater_chase_rainbow_reverse},//彩虹灯效反向
	{ws281x_theater_chase_rainbow_forward},//彩虹灯正向
};

void light_effect_mode_handle()
{
	if(light_effect_dazzling_handle[get_light_effect_enum()].handle)
	{
		light_effect_dazzling_handle[get_light_effect_enum()].handle(get_light_effect_enum(),(1000/(get_light_wait()+1)),get_light_len(),get_light_buf());
	}
}

void light_effect_loop()
{
    while(1)
    {
		light_effect_mode_handle();
    }
}

void task_light_effect_dazzling_init()
{
    xTaskCreate(light_effect_loop,"app_logic_loop",LIGHT_EFFECT_LOOP_SIZE,NULL,TASK_PROP_APP,&thread_light_effect);
}